from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
import joblib #jbolib模块

# 自己定义的kmeans算法
class Mykmeans():

    def __init__(self, data=None):
        self.data = data

    # 主要的处理函数 返回
    def parse(self):
        original_data = load_iris()
        data = original_data.data
        pca = PCA(n_components=3)     # 降维到多少要注意！！！！！！！！！！！！
        new_data = pca.fit_transform(data)   # 先降维数据
        ''' 注意这里的n_clusters 根据题目要求来定'''
        kmeans = KMeans(n_clusters=3, random_state=0).fit(new_data)  # 参数可查看https://blog.csdn.net/weixin_42468475/article/details/105658691?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-105658691-blog-108132679.pc_relevant_aa&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-105658691-blog-108132679.pc_relevant_aa&utm_relevant_index=1
        # 上面是模型的训练
        # 中间是模型的保存

        #保存Model(注:save文件夹要预先建立，否则会报错)
        joblib.dump(kmeans, r'./save/kmeans.pkl')
        # 下面是预测和画图
        pred = kmeans.fit_predict(new_data)
        #查看聚类好的标签
        labels = kmeans.labels_
        sumcluster = {'0':0, '1':0, '2':0}     # 根据聚类规定的K值调整字典
        for i in range(0, len(pred)):
            if pred[i] == 0:
                sumcluster['0'] += 1
            elif pred[i] == 1:
                sumcluster['1'] += 1
            elif pred[i] == 2:
                sumcluster['2'] += 1
        print(sumcluster)
        #可视化 降维+聚类 的效果
        ax = plt.subplot(projection='3d')
        ax.scatter3D(new_data[:,0], new_data[:,1], new_data[:,2], c=labels, alpha=1)  # 如果特征不是三维的 就尝试用二维投影
        plt.show()

    def evaluation(self):
        # 评价kmeans算法的指标 可详见https://blog.csdn.net/weixin_36486455/article/details/112379886
        '''https://blog.csdn.net/l974415301/article/details/87885141?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-87885141-blog-121519176.topnsimilarv1&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-87885141-blog-121519176.topnsimilarv1&utm_relevant_index=1'''

        # 这里以 轮廓系数 和 Calinski-Harabaz Index 为例

        from sklearn import metrics
        original_data = load_iris()
        data = original_data.data

        # 轮廓系数
        # scores = []
        # for i in range(2, 100):
        #     km = KMeans(        n_clusters=i,
        #                         init='k-means++',
        #                         n_init=10,
        #                         max_iter=300,
        #                         random_state=0      )
        #     km.fit(data)
        #     scores.append(metrics.silhouette_score(data, km.labels_ , metric='euclidean'))
        # plt.plot(range(2,100), scores, marker='o')
        # plt.xlabel('Number of clusters')
        # plt.ylabel('silhouette_score')
        # plt.show()

        # Calinski-Harabaz Index 
        ch_scores = []
        for i in range(2, 100):
            km = KMeans(        n_clusters=i,
                                init='k-means++',
                                n_init=10,
                                max_iter=300,
                                random_state=0      )
            km.fit(data)
            ch_scores.append(metrics.calinski_harabasz_score(data, km.labels_))
        plt.plot(range(2,100), ch_scores, marker='o')
        plt.xlabel('Number of clusters')
        plt.ylabel('calinski_harabaz_score')
        plt.show()




if __name__ == '__main__':
    mk = Mykmeans()
    # mk.parse()
    #读取Model
    # clf3 = joblib.load('./save/kmeans.pkl')
    
    #测试读取后的Model
    # print(clf3.predict(np.array([[1,2,3]])))

    # 模型检验
    mk.evaluation()